package com.zmn.plat.anole.config.interceptor;


import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.plat.anole.interfaces.IEncryptDecrypt;
import com.zmn.plat.common.util.encrypt.annotation.EncryptDecryptClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects;
import java.util.Properties;

/**
 * 描述: Mybatis 返回值加解密拦截器
 *
 * @author jiafei
 * @version v1.0
 * @since 2021/8/25 17:37
 */
@Intercepts({
		@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
@Component
@Slf4j
public class ResultInterceptor implements Interceptor {

	@Resource
	private IEncryptDecrypt encryptDecrypt;

	@Override
	public Object intercept(Invocation invocation) throws Throwable {

		Object result = invocation.proceed();
		if (Objects.isNull(result)) {
			return null;
		}
		if (result instanceof ArrayList) {
			ArrayList<?> resultList = (ArrayList<?>) result;
			if (CollectionUtil.isNotNullOrEmpty(resultList) && needToDecrypt(resultList.get(0))) {
				Class<?> objectClass = resultList.get(0).getClass();
				EncryptDecryptClass encryptDecryptClass = AnnotationUtils.findAnnotation(objectClass,
																						 EncryptDecryptClass.class);
				encryptDecrypt.decrypt(resultList, encryptDecryptClass.key());
			}
		} else {
			if (needToDecrypt(result)) {
				Class<?> objectClass = result.getClass();
				EncryptDecryptClass encryptDecryptClass = AnnotationUtils.findAnnotation(objectClass,
																						 EncryptDecryptClass.class);
				encryptDecrypt.decrypt(Collections.singletonList(result), encryptDecryptClass.key());
			}
		}
		return result;
	}

	public boolean needToDecrypt(Object object) {
		if (Objects.isNull(object)) {
			return false;
		}

		Class<?> objectClass = object.getClass();
		EncryptDecryptClass encryptDecryptClass = AnnotationUtils.findAnnotation(objectClass,
																				 EncryptDecryptClass.class);
		return Objects.nonNull(encryptDecryptClass);
	}

	@Override
	public Object plugin(Object target) {

		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {

	}

}

